<?php
/**
 * @author Erling Owe <erling.owe@gmail.com>
 * @package Core
 * @subpackage Presentation
 */

namespace Core\Presentation\HTML;

class Document extends Element {

    // As HTML5 is the only supported document type, we hardcode it.
    private $constDocumentType = HTML5;

    private $NodeCollection;
    private $arrCSSs = array ();
    private $arrJSs = array ();
    private $arrStyles = array ();

    // Public members.
    private $_Base;
    private $_Title;

    // Public write only members.
    private $_Tab = "    ";

    // Public read only members.
    // $_HTML is also be available as a public read only member.


    function __construct ( $strHTML = null ) {
        if ( $strHTML ) {
            // TODO: Create the document from HTML.
        } else {
            // Create a new document.
            parent::__construct( $this, "body" );
        }
        $this->NodeCollection = new NodeCollection ();
    }

    function __get ( $strMemberName ) {

        switch ( $strMemberName ) {

            case "Base":
                return $this->_Base;

            case "HTML":
                return $this->getHTML();

            case "Title":
                return $this->_Title;

        }

    }

    function __set ( $strMemberName, $mixMemberValue ) {

        switch ( $strMemberName ) {

            case "Base":
                // TODO: Validate $mixMemberValue.
                $this->_Base = $mixMemberValue;
                break;

            case "Tab":
                // TODO: Validate $mixMemberValue.
                $this->_Tab = $mixMemberValue;
                break;

            case "Title":
                // TODO: Validate $mixMemberValue.
                $this->_Title = $mixMemberValue;
                break;

        }

    }

    /**
     * Adds a stylesheet to the document.
     *
     * @param string $strURI URI (relative to the base, if set).
     */
    public function addCSS ( $strURI ) {
        $this->arrCSSs[] = $strURI;
    }

    /**
     * Adds a JS-file to the document.
     *
     * @param string $strURI URI (relative to the base, if set).
     */
    public function addJS ( $strURI ) {
        $this->arrJSs[] = $strURI;
    }

    public function addScript ( $strScript ) {

    }

    /**
     * Adds a style to the document
     *
     * @param string $strSelector
     * @param string $strName
     * @param string $strValue
     */
    public function addStyle ( $strSelector, $strName, $strValue ) {
        $this->arrStyles[$strSelector][$strName] = $strValue;
    }

    /**
     * Creates an element.
     *
     * @param string $strTagName
     * @return Core_Presentation_HTML_Element
     */
    public function createElement ( $strTagName ) {
        $objElement = new Element ( $this, $strTagName );
        $this->NodeCollection[] = $objElement;
        return $objElement;
    }

    /**
     * Creates a text node.
     *
     * @param string $strText
     * @return Core_Presentation_HTML_TextNode
     */
    public function createTextNode ( $strText ) {
        $objTextNode = new TextNode ( $this, $strText );
        $this->NodeCollection[] = $objTextNode;
        return $objTextNode;

    }

    public function createWidget () {

    }

    public function getTab ( $intTimes = 1 ) {
        $strReturn = "";
        $i = 1;
        while ( $i <= $intTimes ) {
            $strReturn .= $this->Tab;
            $i++;
        }
        return $strReturn;
    }

    /**
     * Gets the HTML for the entire document.
     *
     * @return string
     */
    protected function getHTML () {

        switch ( $this->constDocumentType ) {

            case HTML5:

                $strReturn = "<!DOCTYPE html>\r\n\r\n";
                $strReturn .= "<html>\r\n\r\n";
                $strReturn .= "<head>\r\n";
                $strReturn .= $this->getTab() . "<title>" . $this->Title . "</title>\r\n";

                if ( $this->Base ) {
                    $strReturn .= $this->getTab() . '<base href="' . $this->Base . '">' . "\r\n";
                }

                foreach ( $this->arrCSSs as $strURI ) {
                    $strReturn .= $this->getTab() . '<link rel="stylesheet" type="text/css" href="' . $strURI . '">' . "\r\n";
                }

                if ( count( $this->arrStyles ) != 0 ) {
                    $strReturn .= $this->getTab() . "<style>\r\n\r\n";
                    ksort( $this->arrStyles );
                    foreach ( $this->arrStyles as $strSelector => $arrValues ) {
                        $strReturn .= $this->getTab(2) . $strSelector . " {\r\n";
                        ksort( $arrValues );
                        foreach ( $arrValues as $strName => $strValue ) {
                            $strReturn .= $this->getTab(3) . $strName . ": " . $strValue . ";\r\n";
                        }
                        $strReturn .= $this->getTab(2) . "}\r\n\r\n";
                    }
                    $strReturn .= $this->getTab() . "</style>\r\n";
                }

                $strReturn .= "</head>\r\n\r\n";

                $strReturn .= parent::getHTML();

                $strReturn .= "\r\n\r\n</html>\r\n";

                break;

        }

        return $strReturn;

    }
    

    // Overwrite Element's implementation of NodeCollectionA.

    /**
     * Gets all descending nodes matching the expression.
     */
    public function find ( $strExpression = null ) {
        return $this->NodeCollection->all( $strExpression );
    }

}

?>